﻿using System.Drawing;

namespace XYAC.Framework.MonitorTireMaterialManual.DataExporter
{
    /// <summary>
    /// 基础轮廓类，提供测量数据的处理逻辑以及关键点、厚度和底部高度的计算。
    /// </summary>
    public abstract class BaseProfile
    {
        /// <summary>
        /// 底部高度点列表。
        /// </summary>
        protected PointDataList m_BottomHeightPoints = new PointDataList();

        /// <summary>
        /// 颜色，默认为黑色。
        /// </summary>
        private System.Drawing.Color m_Color = System.Drawing.Color.Black;

        /// <summary>
        /// 尺寸。
        /// </summary>
        protected SizeF m_Size;

        /// <summary>
        /// 厚度点列表。
        /// </summary>
        protected PointDataList m_ThicknessPoints = new PointDataList();

        /// <summary>
        /// X轴参考值。
        /// </summary>
        protected float m_XReference;

        /// <summary>
        /// 获取指定X轴位置的底部高度。
        /// </summary>
        /// <param name="X">X轴位置。</param>
        /// <returns>底部高度。</returns>
        public float BottomHeight(float X)
        {
            return this.m_BottomHeightPoints.Y(X);
        }

        /// <summary>
        /// 查找中心参考点。
        /// </summary>
        /// <param name="CenterType">中心类型。</param>
        /// <param name="heighval">高度值列表。</param>
        /// <param name="XInterval">X轴间隔。</param>
        /// <param name="FindLen">查找长度。</param>
        /// <returns>中心参考点位置。</returns>
        public static float FindCenterPosition(CenterType CenterType, List<float> heighval, float XInterval, float FindLen)
        {
            int num5;
            int num2 = heighval.Count / 2;
            int num3 = (int)(FindLen / XInterval);
            int num4 = num2 - num3;
            int num6 = num2 + num3;
            if (num4 < 0) num4 = num2 / 2;
            if (num6 >= heighval.Count) num6 = num2 + num2 / 2;
            switch (CenterType)
            {
                case CenterType.None:
                    return (num2 * XInterval);
                case CenterType.Lowest:
                    for (num5 = num4; num5 < num6; num5++)
                    {
                        if (heighval[num5] < heighval[num4])
                        {
                            num4 = num5;
                        }
                    }
                    return (num4 * XInterval);
                case CenterType.Highest:
                    for (num5 = num4; num5 < num6; num5++)
                    {
                        if (heighval[num5] > heighval[num4])
                        {
                            num4 = num5;
                        }
                    }
                    return (num4 * XInterval);
            }
            return 0f;
        }

        /// <summary>
        /// 查找标准值关键点。
        /// </summary>
        /// <param name="Nominal">名义值。</param>
        /// <param name="Measuring">测量值。</param>
        /// <returns>关键点列表。</returns>
        public static List<PointF> FindStandKeyValue(Nominal Nominal, Measuring Measuring)
        {
            float RefX_ChaYi = Nominal.m_XReference - Measuring.XReference;
            List<PointF> list = new List<PointF>();
            for (int i = 0; i < Nominal.KeyPoints.Count; i++)
            {
                PointData p = new PointData(new PointF(Nominal.KeyPoints[i].Point.X - Nominal.m_XReference, Nominal.KeyPoints[i].Point.Y), Nominal.KeyPoints[i].XOffset, Nominal.KeyPoints[i].YOffset);
                Random R = new Random(DateTime.Now.Millisecond);
                if (i == 0)
                {
                    PointF pp = Measuring.ThicknessPoints[0].Point;
                    list.Add(pp);
                }
                else if (i == (Nominal.KeyPoints.Count - 1)) // 最右边点
                {
                    PointF pp = Measuring.ThicknessPoints[Measuring.ThicknessPoints.Count - 1].Point;
                    list.Add(pp);
                }
                else if (Nominal.KeyPoints.Count % 2 > 0 && i == Nominal.KeyPoints.Count / 2 && Nominal.IsSymm)
                {
                    list.Add(new PointF(Measuring.XReference, Measuring.ThicknessVal(Measuring.XReference)));
                }
                else
                {
                    list.Add(GetKey(p, Measuring));
                }
            }
            return list;
        }

        /// <summary>
        /// 更新厚度点差异列表。
        /// </summary>
        /// <param name="Nominal">名义值。</param>
        /// <param name="Measuring">测量值。</param>
        /// <returns>点差异列表。</returns>
        public static List<PointF> Update(Nominal Nominal, Measuring Measuring)
        {
            List<PointF> lstPoint = new List<PointF>();
            PointDataList MPD = Measuring.ThicknessPoints.SetXOffset(Measuring.XReference);
            PointDataList NPD = Nominal.ThicknessPoints.SetXOffset(Nominal.XReference);
            for (int i = 0; i < MPD.Count; i++)
            {
                float ChaYi = MPD[i].Point.Y - NPD.Y(MPD[i].Point.X);
                lstPoint.Add(new PointF(MPD[i].Point.X, ChaYi));
            }
            for (int i = 0; i < Measuring.ThicknessPoints.Count; i++)
            {
                if (lstPoint[i].Y < 1.2)
                {
                    Measuring.ThicknessPoints[i].Point = new PointF(Measuring.ThicknessPoints[i].Point.X, Measuring.ThicknessPoints[i].Point.Y - lstPoint[i].Y / 2);
                }
            }
            return lstPoint;
        }

        /// <summary>
        /// 获取指定点的关键点。
        /// </summary>
        /// <param name="p">点数据。</param>
        /// <param name="Measuring">测量值。</param>
        /// <returns>关键点。</returns>
        private static PointF GetKey(PointData p, Measuring Measuring)
        {
            PointF CurPointF = new PointF(0, 0);
            float ChaYi = 100;
            float StartValue = p.Point.X - p.XOffset + Measuring.XReference;
            float EndValue = p.Point.X + p.XOffset + Measuring.XReference;
            if (StartValue > Measuring.ThicknessPoints[Measuring.ThicknessPoints.Count - 1].Point.X)
                CurPointF = Measuring.ThicknessPoints[Measuring.ThicknessPoints.Count - 1].Point;
            if (EndValue < Measuring.ThicknessPoints[0].Point.X)
                CurPointF = Measuring.ThicknessPoints[0].Point;
            for (int i = 0; i < Measuring.ThicknessPoints.Count; i++)
            {
                if (Measuring.ThicknessPoints[i].Point.X >= StartValue && Measuring.ThicknessPoints[i].Point.X <= EndValue)
                {
                    float CurChaYi = (float)Math.Abs(Measuring.ThicknessPoints[i].Point.Y - p.Point.Y);
                    if (ChaYi > CurChaYi)
                    {
                        ChaYi = CurChaYi;
                        CurPointF = Measuring.ThicknessPoints[i].Point;
                    }
                }
            }
            return CurPointF;
        }

        /// <summary>
        /// 查找关键点。
        /// </summary>
        /// <param name="Nominal">名义值。</param>
        /// <param name="Measuring">测量值。</param>
        /// <returns>关键点列表。</returns>
        public static List<PointF> FindKey(Nominal Nominal, Measuring Measuring)
        {
            Key key = new Key(Nominal, Measuring); // 计算所有关键点
            List<PointF> list = new List<PointF>();
            for (int i = 0; i < key.KeyX.Count; i++)
            {
                list.Add(new PointF(key.KeyX[i], Measuring.ThicknessPoints.Y(key.KeyX[i])));
            }
            return list;
        }

        /// <summary>
        /// 获取指定X轴位置的高度值。
        /// </summary>
        /// <param name="X">X轴位置。</param>
        /// <returns>高度值。</returns>
        public float HeightVal(float X)
        {
            return (this.ThicknessVal(X) + this.BottomHeight(X));
        }

        /// <summary>
        /// 获取指定X轴位置的厚度值。
        /// </summary>
        /// <param name="X">X轴位置。</param>
        /// <returns>厚度值。</returns>
        public float ThicknessVal(float X)
        {
            return this.m_ThicknessPoints.Y(X);
        }

        /// <summary>
        /// 获取或设置X轴参考值。
        /// </summary>
        public virtual float XReference
        {
            get
            {
                return this.m_XReference;
            }
            set
            {
                this.m_XReference = value;
            }
        }

        /// <summary>
        /// 获取底部高度点列表。
        /// </summary>
        public PointDataList BottomHeightPoints
        {
            get
            {
                if ((this.m_ThicknessPoints.Count > 0) && (this.m_BottomHeightPoints.Count == 0))
                {
                    for (int i = 0; i < this.m_ThicknessPoints.Count; i++)
                    {
                        this.m_BottomHeightPoints.Add(new PointData(new PointF(this.m_ThicknessPoints[i].Point.X, 0f)));
                    }
                }
                return this.m_BottomHeightPoints;
            }
        }

        /// <summary>
        /// 获取或设置轮廓颜色。
        /// </summary>
        public System.Drawing.Color Color
        {
            get
            {
                return this.m_Color;
            }
            set
            {
                this.m_Color = value;
            }
        }

        public virtual float Area
        {
            get
            {
                return (this.LeftArea + this.RightArea);
            }
        }
        /// <summary>
        /// 获取轮廓左侧面积。
        /// </summary>
        public virtual float LeftArea
        {
            get
            {
                float num = 0f;
                for (int i = 0; i < (this.m_ThicknessPoints.Count - 1); i++)
                {
                    if ((this.m_ThicknessPoints[i].Point.X < this.m_XReference) && (this.m_ThicknessPoints[i + 1].Point.X <= this.m_XReference))
                    {
                        num += ((this.m_ThicknessPoints[i].Point.Y + this.m_ThicknessPoints[i + 1].Point.Y) * (this.m_ThicknessPoints[i + 1].Point.X - this.m_ThicknessPoints[i].Point.X)) / 2f;
                    }
                    else if ((this.m_ThicknessPoints[i].Point.X < this.m_XReference) && (this.m_ThicknessPoints[i + 1].Point.X > this.m_XReference))
                    {
                        num += ((this.m_ThicknessPoints[i].Point.Y + this.m_ThicknessPoints.Y(this.m_XReference)) * (this.m_XReference - this.m_ThicknessPoints[i].Point.X)) / 2f;
                    }
                }
                return num;
            }
        }

        /// <summary>
        /// 获取轮廓右侧面积。
        /// </summary>
        public virtual float RightArea
        {
            get
            {
                float num = 0f;
                for (int i = 0; i < (this.m_ThicknessPoints.Count - 1); i++)
                {
                    if ((this.m_ThicknessPoints[i].Point.X <= this.m_XReference) && (this.m_ThicknessPoints[i + 1].Point.X > this.m_XReference))
                    {
                        num += ((this.m_ThicknessPoints[i + 1].Point.Y + this.m_ThicknessPoints.Y(this.m_XReference)) * (this.m_ThicknessPoints[i + 1].Point.X - this.m_XReference)) / 2f;
                    }
                    else if ((this.m_ThicknessPoints[i].Point.X > this.m_XReference) && (this.m_ThicknessPoints[i + 1].Point.X > this.m_XReference))
                    {
                        num += ((this.m_ThicknessPoints[i].Point.Y + this.m_ThicknessPoints[i + 1].Point.Y) * (this.m_ThicknessPoints[i + 1].Point.X - this.m_ThicknessPoints[i].Point.X)) / 2f;
                    }
                }
                return num;
            }
        }

        /// <summary>
        /// 获取尺寸。
        /// </summary>
        public SizeF Size
        {
            get
            {
                return this.m_Size;
            }
        }

        /// <summary>
        /// 获取厚度点列表。
        /// </summary>
        public PointDataList ThicknessPoints
        {
            get
            {
                return this.m_ThicknessPoints;
            }
        }

    }

}
